/***************************************************************************
 *   Copyright (C) 2009 by Kbranch                                         *
 *   kbranch@kbranch.net                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "mtrand.h"
#include "stats.h"

#ifndef MAINFILE
	#define EXTERN extern
#else
	#define EXTERN
#endif

// #define DEBUG
// #define SWING_DEBUG

typedef long long int int64;

enum Race { ELF, COW };// Character races
enum BuffType { USE, PROC, PASSIVE }; // Buff types - buff is triggered either by manually using it or a random proc, or is always active
enum ProcTrigger { HIT, CRIT, DAMAGE, MISS }; // Proc triggers - proc triggers from a direct damage attack, a crit, any damage, or a miss
enum AttackType { WHITE, YELLOW, TICK }; // Attack types - attack is an auto swing, any direct damage attack that isn't an auto swing, or a DoT tick
enum AttackName { SWING, SHRED, MANGLE_A, RAKE_A, RIP_A, ROAR_A, BITE, FURY_A, BERSERK_A, FFF_A }; // Attacks - auto attack, shred, mangle, rake, rip, savage roar, tiger's fury, berserk, feral faerie fire
enum BuffNum { // Buffs and debuffs
	SOE, // Strength of Earth Totem / Horn of Winter buff
	impSOE, // Improved Strength of Earth Totem buff
	MANGLE_B, // Mangle / Trauma debuff
	RAKE_B, // Rake debuff
	RIP_B, // Rip debuff
	ROAR_B, // Savage Roar buff
	BOM, // Blessing of Might / Battle Shout buff
	FURY_B, // Tiger's Fury buff
	BERSERK_B, // Berserk buff
	FFF_B, // Feral Faerie Fire / Curse of Recklessness / Sting debuff
	TRUESHOT, // Trueshot Aura / Unleashed Rage / Abomination's Might buff
	FI, // Ferocious Inspiration / Sanctified Retribution buff
	SR, // Swift Retribution / Improved Moonkin Form buff
	WF, // Windfury Totem buff
	impWF, // Improved Windfury / Improved Icy Talons buff
	MOTW, // Mark of the Wild buff
	impMOTW, // Improved Mark of the Wild buff
	BOK, // Blessing of Kings buff
	HP, // Heroic Presence buff
	SUNDER, // Sunder Armor / Expose Armor / Acid Spit debuff
	HOC, // Heart of the Crusader / Master Poisoner / Totem of Wrath debuff
	BF, // Blood Frenzy / Savage Combat debuff
	TRINKET1, // Proc / use from trinket 1
	TRINKET2, // Proc / use from trinket 2
	WEAPONENCHANT, // Proc from the weapon enchant
	HEROISM, // Heroism / Bloodlust buff
	impBOM, // Improved Blessing of Might / Improved Battle Shout buff
	MANGLEIDOL, // Buff from Idol of the Corruptor
	MUTILATIONIDOL // Buff from Idol of Mutilation
};

// Holds information about an attack (Shred, Mangle, Rake, etc)
struct Attack
{
	int64 count; // Total number of times the attack was used
	double damageDealt; // Total damage dealt by the attack, including DoT ticks
	double avgDamage; // Average non-crit direct damage dealt by the attack
	double avgTick; // Average non-crit tick damage dealt by the attack
	double perCP; // Damage added per combo point for a finisher
	double staticDamage; // Base damage for a finisher
	double extraEnergyDamage; // Added FB damage per extra point of energy
	int cost; // Energy cost of the attack
	int64 hits; // Total number of direct damage hits
	int64 tickHits; // Total number of tick hits
	int64 crits; // Total number of direct damage crits
	int64 tickCrits; // Total number of tick crits
	int64 glances; // Total number of glancing blows - only applies to white damage
	int64 misses; // Total number of misses
	int isBleed; // Whether the attack counts as a bleed
};

// Holds information for various buffs
struct Buff
{
	int type; // Buff type, can be USE, PROC, or PASSIVE
	int enabled; // Whether the buff should be used
	int active; // Whether the buff is currently active, only applies to USE and PROC
	int trigger; // What triggers the buff, only applies to PROC
	int64 cooldown; // Cooldown time of the buff
	int64 nextCooldown; // The time when the buff will next be cooled down
	int64 duration; // Duration of the buff
	int64 endTime; // Time the buff will end
	Stats stats; // The various stats the buff grants
	int canTick; // Whether the buff ticks
	int64 lastTrigger; // Last time the buff was triggered
	int64 lastTick; // Last time the buff ticked
	int64 nextTick; // The next time the buff will tick
	int64 lastFaded; // Last time the buff ended
	int64 tickFrequency; // Amount of time between ticks
	int64 downTime; // Amount of time the buff has been inactive
	int64 upTime; // Amount of time the buff has been active
	int64 timeLeft; // Amount of time left on the buff - only calculated when needed
	double avgTick; // Average damage dealt by a non-crit tick - differs from Attack.avgTick in that this is calculated at the application of the buff and does not change based on stat changes
	double procChance; // Chance the proc will trigger on a single event
};

struct Talents
{
	int ferocity; // Reduces Mangle and Rake energy cost by 1 per point (0-5)
	int feralAggression; // Increases Ferocious Bite damage by 3% per point (0-5)
	int savageFury; // Increases Mangle and Rake damage by 10% per point (0-2)
	int feralInstinct; // Increases swipe damage by 5% per point - currently not used (0-3)
	int sharpenedClaws; // Increases crit chance by 2% per point (0-3)
	int primalFury; // 50% chance to generate an extra combo point on crits per talent point - currently either 0% or 100% chance.  One point does nothing.(0-2)
	int primalPrecision; // Increases expertise by 5 and reduces energy lost on finisher misses by 40% per point (0-2)
	int predatoryStrikes; // Increases attack power by 40 and weapon attack power by 7% (20% at max) per point (0-3)
	int shreddingAttacks; // Reduces energy cost of Shred by 9 per point (0-2)
	int survivalOfTheFittest; // Increases all stats by 2% per point (0-3)
	int heartOfTheWild; // Increases attack power by 2% per point (0-5)
	int leaderOfThePack; // Increases crit chance by 5% (0-1)
	int predatoryInstincts; // Increases damage done by crits by 3% (10% at max) per point (0-3)
	int mangle; // Deals damage and increases bleed damage by 30% for 12 seconds - currently not used, assumed to always be available (0-1) 
	int improvedMangle; // Reduces energy cost of Mangle by 2 per point (0-3)
	int kingOfTheJungle; // Causes Tiger's Fury to also grant 20 energy per point (0-3)
	int rendAndTear; // Increases Shred damage on bleeding targets by 4% and increases Ferocious Bite crit chance by 5% per point (0-5)
	int primalGore; // Allows Rip ticks to crit (0-1)
	int berserk; // Reduces energy cost of all abilities by 50% for 15 seconds, 3 minute cooldown (0-1)
	
	int improvedMarkOfTheWild; // Increases all stats by 1% per point (0-2)
	int naturalist; // Increases physical damage by 2% per point (0-5)
	int omenOfClarity; // Allows auto swings to have a chance to reduce the energy cost of the next attack by 100% (0-1)
	int masterShapeshifter; // Increases crit chance by 2% per point (0-2)
};

struct UpcomingAttack
{
	int name;
	int64 time;
};

// Time resolution
EXTERN const int64 PRECISION = 10000000;

EXTERN const int numAttacks = 10;
EXTERN const int numBuffs = 29;
EXTERN int numActiveBuffs;

EXTERN Attack attacks[numAttacks]; // Array holding all the information about the various attacks
EXTERN Buff buffs[numBuffs]; // Array holding all the information about the various buffs
EXTERN int activeBuffs[numBuffs]; // Array holding the IDs of all active buffs
EXTERN const char names[][numBuffs] = {"Swing", "Shred", "Mangle", "Rake", "Rip", "Roar", "Bite", "Fury", "Berserk", "FFF", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "Trinket 1", "Trinket 2", "Weapon enchant", "Heroism", "26"}; // Names of the more important buffs and attacks - used largely for debug output

// Simulation settings
EXTERN int latency; // Connection latency / reaction time to simulate
EXTERN int64 fightLength; // Length of an individual fight
EXTERN int numFights; // Number of fights to simulate
EXTERN int minRoarPoints; // Minimum combo points required before Savage Roar will be considered - ignored if Savage Roar is down
EXTERN int maxRoarClip; // Maximum time left on Savage Roar before it can be used
EXTERN int64 trinket1Delay; // Amount of time to delay the first trinket1 proc
EXTERN int64 trinket2Delay; // Amount of time to delay the first trinket2 proc
EXTERN bool mangleBot; // Whether mangle is assumed to always be on the target
EXTERN bool bleedBot; // Whether the target is assumed to always be bleeding
EXTERN bool useShred; // Whether Shred should be used to generate combo points

// Internal variables
EXTERN UpcomingAttack nextAttack; // The attack that's queued up to be used next
EXTERN Stats currentStats; // Player's current stats
EXTERN Stats staticStats; // Player's stats that don't come from temporary buffs
EXTERN double critMod; // Bonus used to calculate crit damage
EXTERN bool isBleeding; // Whether the target currently has a bleed active
EXTERN int64 lastGCDAttackTime; // The last time a GCD was triggered
EXTERN int energy; // Current energy
EXTERN int64 lastEnergyTick; // Last time a point of energy was gained
EXTERN int comboPoints; // Current number of combo points
EXTERN int shredGlyphCounter; // Number of shreds used on the current Rip
EXTERN bool omenActive; // Whether Omen of Clarity is currently active
EXTERN int64 currentTime; // Current time in the current fight
EXTERN int64 lowestBuffTime; // The time the lowest buff will expire
EXTERN int64 trinketOverlapTime; // Amount of time both trinket procs are up at the same time
EXTERN Talents talents; // Holds information on which talents are active

// Extra stat amounts - passed as command line arguments to help the frontend determine stat weights
EXTERN int agiOffset;
EXTERN int hasteOffset;
EXTERN int arPenOffset;
EXTERN int hitOffset;
EXTERN int expertiseOffset;
EXTERN int critOffset;
EXTERN int apOffset;
EXTERN int weaponAPOffset;
EXTERN int strOffset;

// Character settings
EXTERN int race; // Character race - ELF or COW

EXTERN bool REDMeta; // +3% crit damage meta gem

EXTERN bool ripGlyph; // +4 seconds to Tip
EXTERN bool shredGlyph; // +2 seconds to Rip per Shred, max 6 seconds
EXTERN bool roarGlyph; // Savage Roar grants 3% more damage
EXTERN bool mangleGlyph; // +6 seconds to Mangle

EXTERN bool twoT7; // +4 seconds to Rip
EXTERN bool fourT7; // -3 seconds from Tiger's Fury cooldown
EXTERN bool twoT8; // Clearcast chance from bleeds
EXTERN bool fourT8; // +8 seconds to Savage Roar
EXTERN bool twoT9; // +3 seconds to Rake
EXTERN bool fourT9; // +5% crit to Rip and Ferocious Bite

EXTERN bool ripIdol; // +21 Rip tick damage per combo point
EXTERN bool shredIdol; // +203 damage to Shred
EXTERN bool mangleIdol; // +153 agility for 12 seconds every mangle
EXTERN bool mutilationIdol; // Chance of +200 agi after Mangle and Shred

// Simulation constants
EXTERN const double bossCritReduction = 0.048; // Crit chance reduction from the level difference of the target
EXTERN const double omenProcChance = 3.5/60; // Chance for Omen of Clarity to proc
EXTERN const double twoT8ProcChance = 1.2/60; // Chance for the two piece T8 set bonus to proc
EXTERN const double mutilationIdolProcChance = 0.70; // Chance for the Idol of Mutilation bonus to proc
EXTERN const double baseMissChance = 0.08; // Base chance to miss the target
EXTERN const double baseDodgeChance = 0.065; // Base chance to be dodged by the target
EXTERN const double glanceChance = 0.24; // Chance for a white attack to glance
EXTERN const double glanceMod = 0.75; // Damage modifier for a glance
EXTERN const int64 baseAttackSpeed = PRECISION; // Unmodified auto swing speed
EXTERN const int gcd = PRECISION; // Global cooldown duration - the minimum time between yellow attacks
EXTERN const char configName[] = "branchsim.cfg"; // File name of the configuration file to use
EXTERN const int maxBiteExtraEnergy = 30; // Maximum amount of extra energy Ferocious Bite can use
EXTERN const int maxEnergy = 100; // Maximum energy
EXTERN const int energyTickRate = 0.1 * PRECISION; // Amount of time it takes to regenerate 1 energy

void Init(); // Initializes attack and buff values
void CalculateStats(); // Calculates current stats based on all talents, buffs, and gear
void CalculateAverageDamage(); // Calculates the average damage of all attacks based on current stats
void DoNextAttack(MTRand_closed &rand); // Instantly performs the attack that is queued up
int64 GetLowestBuff(); // Returns the time the lowest buff will expire
void CheckBuffDurations(); // Disables expired buffs
void Swing(MTRand_closed &rand); // Performs an auto attack
void PrintReport(int timeTaken, float fightDamage[]); // Prints the results of the simulation
void ChooseNextAttack(); // Chooses and queues up the next attack
int64 TimeUntilEnergy(int cost); // Returns the time it will take for 'cost' energy to be available
int64 GetAttackTime(Attack attack); // Returns the earliest time 'attack' can be used
void CheckProcs(AttackType attackType, int crit, int attack, MTRand_closed &rand); // Checks whether any procs should be triggered for a specific attack
bool CanBite(); // Returns 1 or 0 depending on whether Ferocious Bite is an appropriate next attack
void LoadSettings(); // Loads various settings and values from a file
Buff GetProc(const char procName[100], Buff tempBuff); // Returns a Buff struct filled with proc information for the proc name passed to it
void DoAttack(AttackName attack, int isFinisher, int isDebuff, int roll, double damage, MTRand_closed &rand); // Executes most of a specific attack.  Special effects are still handled outside the function
UpcomingAttack CreateAttack(AttackName attackName); // Returns an UpcomingAttack struct containing attackName and the time the attack will be able to be executed
UpcomingAttack CreateAttack(AttackName attackName, int64 targetTime); // Delays the attack until targetTime if the attack is able to be executed before that